wayland: Don't recreated keymaps on layout change
authorMatthias Clasen <mclasen@redhat.com>
Sat, 23 Mar 2013 22:02:28 +0000 (18:02 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Sat, 23 Mar 2013 22:04:15 +0000 (18:04 -0400)
The GDK model for keymaps expects the keymap object to stay
around and emit a ::keys-changed signal. So, do that. This
should make layout changes work, but it remains untested since
weston does not support layout changes at runtime.

At the same time, plug a memory leak where GdkWaylandKeymap
forgot to free its xkb objects in finalize.
https://bugzilla.gnome.org/show_bug.cgi?id=696339

gdk/wayland/gdkdevice-wayland.c
gdk/wayland/gdkkeys-wayland.c
gdk/wayland/gdkprivate-wayland.h

index 91056aeaf09dfc107a74ba7043c9758b95e48a70..800229cf0ea7fc6ccf0c6c519bf302fe2b477585 100644 (file)
@@ -777,10 +777,11 @@ keyboard_handle_keymap (void               *data,
                        uint32_t            size)
 {
   GdkWaylandDeviceData *device = data;
-  if (device->keymap)
-    g_object_unref (device->keymap);
 
-  device->keymap = _gdk_wayland_keymap_new_from_fd (format, fd, size);
+  _gdk_wayland_keymap_update_from_fd (device->keymap, format, fd, size);
+
+  g_signal_emit_by_name (device->keymap, "keys-changed");
+  g_signal_emit_by_name (device->keymap, "state-changed");
 }
 
 static void
index 4d10e679460b783a4bf9e087f0e0658c0996873b..c2d07eb2a5c62ed119aba83682108333f413c44f 100644 (file)
@@ -66,6 +66,11 @@ G_DEFINE_TYPE (GdkWaylandKeymap, _gdk_wayland_keymap, GDK_TYPE_KEYMAP)
 static void
 gdk_wayland_keymap_finalize (GObject *object)
 {
+  GdkWaylandKeymap *keymap = GDK_WAYLAND_KEYMAP (object);
+
+  xkb_keymap_unref (keymap->xkb_keymap);
+  xkb_state_unref (keymap->xkb_state);
+
   G_OBJECT_CLASS (_gdk_wayland_keymap_parent_class)->finalize (object);
 }
 
@@ -228,31 +233,34 @@ _gdk_wayland_keymap_new ()
   return GDK_KEYMAP (keymap);
 }
 
-GdkKeymap *
-_gdk_wayland_keymap_new_from_fd (uint32_t format,
-                                 uint32_t fd, uint32_t size)
+void
+_gdk_wayland_keymap_update_from_fd (GdkKeymap *keymap,
+                                    uint32_t   format,
+                                    uint32_t   fd,
+                                    uint32_t   size)
 {
-  GdkWaylandKeymap *keymap;
+  GdkWaylandKeymap *keymap_wayland = GDK_WAYLAND_KEYMAP (keymap);
   struct xkb_context *context;
   char *map_str;
 
-  keymap = g_object_new (_gdk_wayland_keymap_get_type(), NULL);
-
   context = xkb_context_new (0);
 
   map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
-  if (map_str == MAP_FAILED) {
-    close(fd);
-    return NULL;
+  if (map_str == MAP_FAILED)
+    {
+      close(fd);
+      return;
   }
 
-  keymap->xkb_keymap = xkb_keymap_new_from_string (context, map_str, format, 0);
+  xkb_keymap_unref (keymap_wayland->xkb_keymap);
+  keymap_wayland->xkb_keymap = xkb_keymap_new_from_string (context, map_str, format, 0);
   munmap (map_str, size);
   close (fd);
-  keymap->xkb_state = xkb_state_new (keymap->xkb_keymap);
-  xkb_context_unref (context);
 
-  return GDK_KEYMAP (keymap);
+  xkb_state_unref (keymap_wayland->xkb_state);
+  keymap_wayland->xkb_state = xkb_state_new (keymap_wayland->xkb_keymap);
+
+  xkb_context_unref (context);
 }
 
 struct xkb_keymap *_gdk_wayland_keymap_get_xkb_keymap (GdkKeymap *keymap)
index 0b7f5b570fe9c1965d5d89a8b34c84303edb62f4..9c958e44706c3ed95f5e33aa0fe24fd5db5baf1f 100644 (file)
@@ -49,8 +49,10 @@ void _gdk_wayland_window_add_focus    (GdkWindow *window);
 void _gdk_wayland_window_remove_focus (GdkWindow *window);
 
 GdkKeymap *_gdk_wayland_keymap_new (void);
-GdkKeymap *_gdk_wayland_keymap_new_from_fd (uint32_t format,
-                                            uint32_t fd, uint32_t size);
+void       _gdk_wayland_keymap_update_from_fd (GdkKeymap *keymap,
+                                               uint32_t   format,
+                                               uint32_t   fd,
+                                               uint32_t   size);
 struct xkb_state *_gdk_wayland_keymap_get_xkb_state (GdkKeymap *keymap);
 struct xkb_keymap *_gdk_wayland_keymap_get_xkb_keymap (GdkKeymap *keymap);